{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "In this notebook you will see how to set simple constraints on BN learning and how sometimes Gobnilp's parameters need to be changed from their default values to make this possible. We start by learning a BN from `discrete.dat` with no parent set limit."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Using license file /home/james/gurobi.lic\n",
      "Academic license - for non-commercial use only\n",
      "Changed value of parameter PreCrush to 1\n",
      "   Prev: 0  Min: 0  Max: 1  Default: 0\n",
      "Changed value of parameter CutPasses to 100000\n",
      "   Prev: -1  Min: -1  Max: 2000000000  Default: -1\n",
      "Changed value of parameter GomoryPasses to 100000\n",
      "   Prev: -1  Min: -1  Max: 2000000000  Default: -1\n",
      "Changed value of parameter MIPFocus to 2\n",
      "   Prev: 0  Min: 0  Max: 3  Default: 0\n",
      "Changed value of parameter ZeroHalfCuts to 2\n",
      "   Prev: -1  Min: -1  Max: 2  Default: -1\n",
      "Changed value of parameter MIPGap to 0.0\n",
      "   Prev: 0.0001  Min: 0.0  Max: inf  Default: 0.0001\n",
      "Changed value of parameter MIPGapAbs to 0.0\n",
      "   Prev: 1e-10  Min: 0.0  Max: inf  Default: 1e-10\n",
      "**********\n",
      "BN has score -24028.0947783535\n",
      "**********\n",
      "A<- -5502.137377150637\n",
      "B<-A -3688.9395212202216\n",
      "C<- -3501.5105385969146\n",
      "D<-A,C -3555.014444236549\n",
      "E<-B,F -4310.304956470649\n",
      "F<- -3470.18794067853\n",
      "**********\n",
      "bnlearn modelstring = \n",
      "[A][B|A][C][D|A:C][E|B:F][F]\n",
      "**********\n",
      "CPDAG:\n",
      "Vertices: A,B,C,D,E,F\n",
      "A-B\n",
      "A->D\n",
      "B->E\n",
      "C->D\n",
      "F->E\n",
      "\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "from pygobnilp.gobnilp import Gobnilp\n",
    "m = Gobnilp()\n",
    "m.learn('discrete.dat',palim=None)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now, suppose, that for some reason we decided that we were only interested in BNs where there was an arrow between C and F - in either direction, i.e. there was an undirected edge between these two nodes in the undirected version of the BN. In Gobnilp, these undirected edges are called `adjacencies` and there are binary variables in the MIP model stored in an Gobnilp attribute called `adjacency` which is a dictionary. Let's have a look at it:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "adjacency is frozenset({'B', 'A'}), MIP variable is <gurobi.Var A-B (value 1.0)>\n",
      "adjacency is frozenset({'A', 'C'}), MIP variable is <gurobi.Var A-C (value 0.0)>\n",
      "adjacency is frozenset({'D', 'A'}), MIP variable is <gurobi.Var A-D (value 1.0)>\n",
      "adjacency is frozenset({'E', 'A'}), MIP variable is <gurobi.Var A-E (value 0.0)>\n",
      "adjacency is frozenset({'F', 'A'}), MIP variable is <gurobi.Var A-F (value 0.0)>\n",
      "adjacency is frozenset({'B', 'C'}), MIP variable is <gurobi.Var B-C (value 0.0)>\n",
      "adjacency is frozenset({'B', 'D'}), MIP variable is <gurobi.Var B-D (value 0.0)>\n",
      "adjacency is frozenset({'B', 'E'}), MIP variable is <gurobi.Var B-E (value 1.0)>\n",
      "adjacency is frozenset({'B', 'F'}), MIP variable is <gurobi.Var B-F (value 0.0)>\n",
      "adjacency is frozenset({'D', 'C'}), MIP variable is <gurobi.Var C-D (value 1.0)>\n",
      "adjacency is frozenset({'D', 'E'}), MIP variable is <gurobi.Var D-E (value 0.0)>\n",
      "adjacency is frozenset({'E', 'F'}), MIP variable is <gurobi.Var E-F (value 1.0)>\n"
     ]
    }
   ],
   "source": [
    "for pair, mipvar in m.adjacency.items():\n",
    "    print('adjacency is {0}, MIP variable is {1}'.format(pair,mipvar))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "So the keys of the dictionary are Python frozensets and the values they map to are Gurobi MIP variables. Each of these MIP variables is binary and indicates whether the adjacency is present. Note that the values of the MIP variables correspond to the learned BN, since we (or rather Gurobi) has already solved the MIP problem.\n",
    "\n",
    "There is however no adjacency variable for C and F. This is because when we were computing local scores from the data, Gobnilp did (by default) 'pruning' - It does not include any parent sets which could not possibly be in an optimal network **assuming no constraints other than acyclicity**. As it happens this led to no parent set for C including F and no parent set for F including C. As a result with these parent sets there can be no adjacency between C and F and so Gobnilp does not create a corresponding adjacency variable.\n",
    "\n",
    "We can have a look at the parent sets which have been created for, say, variables C and F by inspecting the `local_scores` attribute which is a dictionary."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{frozenset(): -3501.5105385969146, frozenset({'D'}): -3490.1353818719726, frozenset({'D', 'A'}): -2703.350235832673, frozenset({'B', 'D'}): -3348.7158947379976}\n",
      "{frozenset(): -3470.18794067853, frozenset({'E'}): -3026.9672848237205, frozenset({'E', 'A'}): -3026.441770621059, frozenset({'B', 'E'}): -2933.7548470815454}\n"
     ]
    }
   ],
   "source": [
    "print(m.local_scores['C'])\n",
    "print(m.local_scores['F'])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "So we have a mapping from parent sets (as frozensets) to the corresponding local score. There is also a binary MIP variable for each child + parent set combination. child+parents is called a 'family' in Gobnilp and the MIP variables are found in the `family` attribute:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{frozenset(): <gurobi.Var C<-{} (value 1.0)>, frozenset({'D'}): <gurobi.Var C<-{D} (value 0.0)>, frozenset({'D', 'A'}): <gurobi.Var C<-{A,D} (value 0.0)>, frozenset({'B', 'D'}): <gurobi.Var C<-{B,D} (value 0.0)>}\n",
      "{frozenset(): <gurobi.Var F<-{} (value 1.0)>, frozenset({'E'}): <gurobi.Var F<-{E} (value 0.0)>, frozenset({'E', 'A'}): <gurobi.Var F<-{A,E} (value 0.0)>, frozenset({'B', 'E'}): <gurobi.Var F<-{B,E} (value 0.0)>}\n"
     ]
    }
   ],
   "source": [
    "print(m.family['C'])\n",
    "print(m.family['F'])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "To find the optimal BN **subject to there being an adjacency between C and F** we need to sure that we do not 'prune away' parent sets needed for this BN. The safe way of acheiving this is to just turn pruning off entirely:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Changed value of parameter PreCrush to 1\n",
      "   Prev: 0  Min: 0  Max: 1  Default: 0\n",
      "Changed value of parameter CutPasses to 100000\n",
      "   Prev: -1  Min: -1  Max: 2000000000  Default: -1\n",
      "Changed value of parameter GomoryPasses to 100000\n",
      "   Prev: -1  Min: -1  Max: 2000000000  Default: -1\n",
      "Changed value of parameter MIPFocus to 2\n",
      "   Prev: 0  Min: 0  Max: 3  Default: 0\n",
      "Changed value of parameter ZeroHalfCuts to 2\n",
      "   Prev: -1  Min: -1  Max: 2  Default: -1\n",
      "Changed value of parameter MIPGap to 0.0\n",
      "   Prev: 0.0001  Min: 0.0  Max: inf  Default: 0.0001\n",
      "Changed value of parameter MIPGapAbs to 0.0\n",
      "   Prev: 1e-10  Min: 0.0  Max: inf  Default: 1e-10\n",
      "**********\n",
      "BN has score -24028.0947783535\n",
      "**********\n",
      "A<- -5502.137377150637\n",
      "B<-A -3688.9395212202216\n",
      "C<- -3501.5105385969146\n",
      "D<-A,C -3555.014444236549\n",
      "E<-B,F -4310.304956470649\n",
      "F<- -3470.18794067853\n",
      "**********\n",
      "bnlearn modelstring = \n",
      "[A][B|A][C][D|A:C][E|B:F][F]\n",
      "**********\n",
      "CPDAG:\n",
      "Vertices: A,B,C,D,E,F\n",
      "A-B\n",
      "A->D\n",
      "B->E\n",
      "C->D\n",
      "F->E\n",
      "\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "m = Gobnilp()\n",
    "m.learn('discrete.dat',palim=None,pruning=False)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We get exactly the same BN since we have yet to add any new constraints. But now at least we have the needed MIP variable available:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<gurobi.Var C-F (value 0.0)>\n"
     ]
    }
   ],
   "source": [
    "adj_cf = m.adjacency[frozenset(['C','F'])]\n",
    "print(adj_cf)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Although `adj_cf` has value 0 in the learned BN, it was not *compelled* to take that value by some constraint. It has the normal bounds for a binary variable: 0 and 1. We can see this by looking at its `lb` (lower bound) and `ub` (upper bound) values. Note that these are Gurobi MIP variable attributes and are not part of Gobnilp. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(0.0, 1.0)"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "adj_cf.lb, adj_cf.ub"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "To fix `adj_cf` to 1 we just alter its lower bound:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "adj_cf.lb = 1"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now we need to re-learn with this new constraint. To do this we call the `learn` method where we start at the stage of having the MIP model."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "**********\n",
      "BN has score -24036.170710864524\n",
      "**********\n",
      "A<- -5502.137377150637\n",
      "B<-A -3688.9395212202216\n",
      "C<- -3501.5105385969146\n",
      "D<-A,C -3555.014444236549\n",
      "E<-B,F -4310.304956470649\n",
      "F<-C -3478.263873189553\n",
      "**********\n",
      "bnlearn modelstring = \n",
      "[A][B|A][C][D|A:C][E|B:F][F|C]\n",
      "**********\n",
      "CPDAG:\n",
      "Vertices: A,B,C,D,E,F\n",
      "A-B\n",
      "A->D\n",
      "B->E\n",
      "C->D\n",
      "C-F\n",
      "F->E\n",
      "\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "m.learn(start='MIP model')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "All is well. As expected we get a BN with the desired link. Adding other simple constraints follows the same recipe. Let's disallow the arrow from F to E (found in the `arrow` attribute dictionary) and relearn:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "**********\n",
      "BN has score -24043.92054159024\n",
      "**********\n",
      "A<-B -4349.791324894952\n",
      "B<-E -4227.543778182593\n",
      "E<- -5468.229676086663\n",
      "C<-F -3509.5864711079375\n",
      "F<-B,E -2933.7548470815454\n",
      "D<-A,C -3555.014444236549\n",
      "**********\n",
      "bnlearn modelstring = \n",
      "[A|B][B|E][E][C|F][F|B:E][D|A:C]\n",
      "**********\n",
      "CPDAG:\n",
      "Vertices: A,B,E,C,F,D\n",
      "A->D\n",
      "B-A\n",
      "B-F\n",
      "E-B\n",
      "E-F\n",
      "C->D\n",
      "F-C\n",
      "\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "m.arrow['F','E'].ub = 0\n",
    "m.learn(start='MIP model')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "It is important to realise that *any* constraint made available by Gurobi can be imposed on the MIP variables Gobnilp has created for learning BNs. For example, we could require that at most 4 of the arrows in the above learned BN are allowed:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[<gurobi.Var A->D (value 1.0)>, <gurobi.Var B->A (value 1.0)>, <gurobi.Var B->F (value 1.0)>, <gurobi.Var C->D (value 1.0)>, <gurobi.Var E->B (value 1.0)>, <gurobi.Var E->F (value 1.0)>, <gurobi.Var F->C (value 1.0)>]\n",
      "**********\n",
      "BN has score -24119.316410157633\n",
      "**********\n",
      "A<- -5502.137377150637\n",
      "B<-A -3688.9395212202216\n",
      "C<- -3501.5105385969146\n",
      "D<-A,C -3555.014444236549\n",
      "E<-B -4854.487880793349\n",
      "F<-B,C,E -3017.2266481599618\n",
      "**********\n",
      "bnlearn modelstring = \n",
      "[A][B|A][C][D|A:C][E|B][F|B:E:C]\n",
      "**********\n",
      "CPDAG:\n",
      "Vertices: A,B,C,D,E,F\n",
      "A-B\n",
      "A->D\n",
      "B-E\n",
      "B->F\n",
      "C->D\n",
      "C->F\n",
      "E->F\n",
      "\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# get all arrows in learned BN. 'X' attribute is value in solution\n",
    "arrs = [v for v in m.arrow.values() if v.X == 1.0]\n",
    "print(arrs)\n",
    "# grab everything from Gurobi\n",
    "from gurobipy import *\n",
    "# add constraint that these variables sum to at most 4\n",
    "m.addConstr(LinExpr([1]*len(arrs),arrs), GRB.LESS_EQUAL, 4)\n",
    "m.learn(start='MIP model')"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.9"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
